home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / ScreenSaver / QD3DModule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  18.4 KB  |  857 lines  |  [TEXT/CWIE]

  1. /*    This is the c file that implements the action for this screen saver.
  2.     See GraphicsModule.c for infomation on how to write your own.
  3.     
  4.     First Version    Andrew Armstrong
  5.     
  6.     © 1995 Berkeley Systems Inc.
  7. */
  8.  
  9. /*
  10. **    TAB SIZE = 4 spaces
  11. */
  12.  
  13. /*
  14. **    TO DO:
  15. **    * Multiple monitors
  16. **    * Make the pixmap point right to the screen for Apple HD Accel
  17. **    * Make the sliders work in demo mode
  18. **    * Handle case where they are not installed (draw error message with WWW Address)
  19. **
  20. **    FUTURE DIRECTIONS
  21. **    * cutsie-ass names on the sliders
  22. */
  23.  
  24. #define FAKE_QD3D_NOT_INSTALLED
  25.  
  26.  
  27. #if 0
  28. #pragma mark INCLUDES
  29. #endif
  30.                 
  31. /*
  32. ** PROJECT INCLUDES
  33. */
  34. #include "QD3DModule.h"
  35. #include "QD3DErrorModule.h"
  36. #include "Q3ADUtilities.h"
  37.  
  38. /*
  39. ** ANSI INCLUDES
  40. */
  41. #include <math.h>
  42. #include <assert.h>
  43. #include <stdlib.h>
  44.  
  45. /*
  46. ** MAC INCLUDES
  47. */
  48. #include <Quickdraw.h>
  49. #include <QDOffscreen.h>
  50. #include <CodeFragments.h>
  51.  
  52. /*
  53. ** MISC INCLUDES
  54. */
  55. #include <QD3DGeometry.h>
  56. #include <QD3DTransform.h>
  57. #include <QD3DMath.h>
  58. #include <QD3DCamera.h>
  59. #include <QD3DLight.h>
  60. #include <QD3DGroup.h>
  61.  
  62. #if 0
  63. #pragma mark CONSTANTS
  64. #endif
  65.                 
  66. /*
  67. ** CONSTANTS
  68. */
  69. #define        kSize                1.0
  70. #define        kSpace                1.0
  71. #define        kLongSize            (sizeof(long))
  72.  
  73. #define        kADParam_Speed        0
  74. #define        kADParam_NumBoxes    1
  75. #define        kADParam_PaneSize    2
  76. #define        kADParam_Dithered    3
  77.  
  78. #if 0
  79. #pragma mark GLOBALS
  80. #endif
  81.                 
  82. /*
  83. ** GLOBALS
  84. */
  85.  
  86. float        gPaneSizeTable[4]    = {0.25, 0.50, 0.75, 1.0};
  87. TQ3Boolean    gHasQuickDraw3D        = kQ3False;
  88. long        gBestMonitor        = 0;
  89. long        gDrawNow            = true;
  90.  
  91. #if 0
  92. #pragma mark PRIVATE STRUCTURES
  93. #endif
  94.  
  95. typedef struct iTQ3ADModule
  96. {
  97.         TQ3ViewObject    view;
  98.         TQ3ShaderObject    shader;
  99.         float            paneSize;
  100.         long            numRows;
  101.         TQ3ADOffscreen    *offscreen;
  102.         
  103. } iTQ3ADModule;
  104.  
  105.  
  106.     
  107. #if 0
  108. #pragma mark PRIVATE FUNCTION DECLARATIONS
  109. #endif
  110.                 
  111. /*
  112. ** PRIVATE FUNCTIONS
  113. */
  114. static TQ3Status         iQ3ADModule_ZeroOut(
  115.                             TQ3ADModule    *ioModule);
  116.  
  117. static TQ3CameraObject    iQ3ADModule_NewCamera(
  118.                             long        numRows);
  119.  
  120. static TQ3GroupObject    iQ3ADModule_NewLightGroup(
  121.                             long        numRows);
  122.  
  123. static TQ3Status         iQ3ADModule_Submit(
  124.                             TQ3ADModule *ioModule);
  125.  
  126.  
  127. #if 0
  128. #pragma mark -
  129. #endif
  130.                 
  131. /******************************************************************************
  132.  **                                                                             **
  133.  **                        PUBLIC FUNCTION DEFINITIONS                             **
  134.  **                                                                             **
  135.  *****************************************************************************/
  136.  
  137. /*===========================================================================*\
  138.  *
  139.  *    Routine:    DoInitialize()
  140.  *
  141.  *    Comments:    
  142.  *
  143. \*===========================================================================*/
  144.  
  145. OSErr DoInitialize(Handle *storage, RgnHandle blankRgn, GMParamBlockPtr params)
  146. {
  147.     mUnused(blankRgn);
  148.     mUnused(params);
  149.     
  150.     
  151.     gBestMonitor    =    Q3ADUtility_GetBestMonitor(params->monitors);
  152.     
  153.     /*
  154.     **    Check to see if we have access to QuickDraw 3D
  155.     */
  156.     gHasQuickDraw3D    =    ((long)Q3Initialize    != kUnresolvedCFragSymbolAddress)    ?
  157.                             kQ3True        :
  158.                             kQ3False    ;
  159.                             
  160. #ifdef FAKE_QD3D_NOT_INSTALLED
  161.  
  162.     gHasQuickDraw3D    = kQ3False;
  163.     
  164. #endif
  165.                         
  166.     if (gHasQuickDraw3D    == kQ3True)    {
  167.     
  168.         /*
  169.         **    We've got it!
  170.         **    Create the QD3D module
  171.         */
  172.         Q3Initialize();
  173.         *storage = (Handle)Q3ADModule_New(params);
  174.         
  175.     }    else {
  176.     
  177.         /*
  178.         **    We don't got it.
  179.         **    Create the QD3D error module which doesn't require
  180.         **    QD3D but is still kinda cool
  181.         */
  182.         *storage = (Handle)Q3ADErrorModule_New(params);
  183.         
  184.     }
  185.     
  186.     if (*storage)
  187.     {
  188.         return noErr;
  189.     }
  190.     else return ModuleError;
  191. }
  192.  
  193.  
  194.  
  195. /*===========================================================================*\
  196.  *
  197.  *    Routine:    DoClose()
  198.  *
  199.  *    Comments:    
  200.  *
  201. \*===========================================================================*/
  202.  
  203. OSErr DoClose(Handle storage,RgnHandle blankRgn,GMParamBlockPtr params)
  204. {
  205.     mUnused(blankRgn);
  206.     mUnused(params);
  207.     
  208.     if (gHasQuickDraw3D    == kQ3True)    {
  209.     
  210.         /*
  211.         **    Dispose of the QD3D module
  212.         */
  213.         if (storage)
  214.             Q3ADModule_Dispose((TQ3ADModule**)storage);
  215.         Q3Exit();
  216.         
  217.     }    else {
  218.     
  219.         /*
  220.         **    Dispose of the error module
  221.         */
  222.         if (storage)
  223.             Q3ADErrorModule_Dispose((TQ3ADErrorModule**)storage);
  224.         
  225.     }
  226.         return noErr;
  227. }
  228.  
  229.  
  230.  
  231. /*===========================================================================*\
  232.  *
  233.  *    Routine:    DoBlank()
  234.  *
  235.  *    Comments:    
  236.  *
  237. \*===========================================================================*/
  238.  
  239. OSErr DoBlank(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params)
  240. {
  241.     mUnused(storage);
  242.     mUnused(blankRgn);
  243.     mUnused(params);
  244.     
  245.     // Simply blanks out the area that we are going to draw in.
  246.     FillRgn(blankRgn, (ConstPatternParam) ¶ms->qdGlobalsCopy->qdBlack);
  247.     
  248.     // If your were going to set a custom palette, now would be a good time.
  249.     // Doing it when the screen is black elimates the palette flash
  250.     
  251.     return noErr;
  252. }
  253.  
  254.  
  255.  
  256. /*===========================================================================*\
  257.  *
  258.  *    Routine:    DoDrawFrame()
  259.  *
  260.  *    Comments:    
  261.  *
  262. \*===========================================================================*/
  263.  
  264. OSErr DoDrawFrame(Handle storage,RgnHandle blankRgn,GMParamBlockPtr params)
  265. {
  266.     OSErr err;
  267.     long    i = 0;
  268.     long    privateSynch;
  269.     mUnused(blankRgn);
  270.     mUnused(params);
  271.     
  272.     privateSynch = params->monitors->monitorList[gBestMonitor].synchFlag;
  273.     
  274.     if ( (privateSynch == false) && (gDrawNow == true))
  275.         gDrawNow = false;
  276.     else if ( (privateSynch == true) && (gDrawNow == false))
  277.         gDrawNow = true;
  278.         
  279.     if (gDrawNow == false)    
  280.         return noErr;
  281.     
  282.     if (gHasQuickDraw3D    == kQ3True)    {
  283.         /*
  284.         **    We're only supposed to draw one frame here but that makes my
  285.         **    Powerbook jerky
  286.         */
  287.         for (i = 0; i < 1; i++) {
  288.         
  289.             err    = TQ3Status_to_OSErr(
  290.                             Q3ADModule_Draw(
  291.                                 *(TQ3ADModule**)storage)
  292.                             );
  293.             if (err != noErr)
  294.                 return err;
  295.         }
  296.         
  297.     }    else {
  298.     
  299.         /*
  300.         **    Dispose of the error module
  301.         */
  302.         if (storage)
  303.             err    = TQ3Status_to_OSErr(
  304.                     Q3ADErrorModule_Draw(*(TQ3ADErrorModule**)storage)
  305.                     );
  306.         
  307.         if (err != noErr)
  308.             return err;
  309.     }
  310.     
  311.     return err;
  312. }
  313.  
  314.  
  315.  
  316. /*===========================================================================*\
  317.  *
  318.  *    Routine:    DoSetUp()
  319.  *
  320.  *    Comments:    
  321.  *
  322. \*===========================================================================*/
  323.  
  324. OSErr DoSetUp(RgnHandle blankRgn,short message,GMParamBlockPtr params)
  325. {
  326.     mUnused(blankRgn);
  327.     mUnused(message);
  328.     mUnused(params);
  329.     
  330.     return noErr;
  331. }
  332.  
  333.  
  334.  
  335. #if 0
  336. #pragma mark -
  337. #endif
  338.                 
  339. /*===========================================================================*\
  340.  *
  341.  *    Routine:    Q3ADModule_New()
  342.  *
  343.  *    Comments:    
  344.  *
  345. \*===========================================================================*/
  346.  
  347. TQ3ADModule **Q3ADModule_New(GMParamBlockPtr params)
  348. {
  349.     TQ3RendererObject        theRenderer        = NULL;
  350.     TQ3DrawContextObject    theDrawContext    = NULL;
  351.     TQ3CameraObject            theCamera        = NULL;
  352.     TQ3GroupObject            theLightGroup    = NULL;
  353.     
  354.     TQ3Status                status            = kQ3Success;
  355.     
  356.     TQ3ADModule                **outModule        = NULL;
  357.     
  358.     Rect                    monitorRect, tempRect, alignedRect;
  359.     
  360.     unsigned long            halfWidth,
  361.                             halfHeight;
  362.                 
  363.     assert(params);
  364.     
  365.     mBailIfNULL_(outModule = (TQ3ADModule **)NewHandle(sizeof(TQ3ADModule)));
  366.     HLock((Handle) outModule);
  367.         
  368.     mBailIfNot_(iQ3ADModule_ZeroOut(*outModule));
  369.     
  370.     (**outModule).paneSize    =
  371.         gPaneSizeTable[params->controlValues[kADParam_PaneSize] - 1];
  372.         
  373.     (**outModule).numRows    =
  374.         (long)(params->controlValues[kADParam_NumBoxes] / 10.0) + 1;
  375.  
  376.     
  377.     /*
  378.     **    OFFSCREEN
  379.     */
  380.     
  381.     /*
  382.     **    Set up the destination rect
  383.     */
  384.     
  385.     monitorRect    =    Q3ADUtility_GetRectOfBestMonitor(params->monitors);
  386.     
  387.     halfWidth    =    (monitorRect.right    - monitorRect.left)    * 0.5;
  388.     halfHeight    =    (monitorRect.bottom    - monitorRect.top)    * 0.5;
  389.                 
  390.     /*
  391.     **    Scale the rect to the percentage of the screen that we want
  392.     */
  393.     SetRect(
  394.         &tempRect,
  395.         (1.0 - (**outModule).paneSize) * halfWidth,
  396.         (1.0 - (**outModule).paneSize) * halfHeight,
  397.         (1.0 + (**outModule).paneSize) * halfWidth,
  398.         (1.0 + (**outModule).paneSize) * halfHeight);
  399.     
  400.     /*
  401.     **    Place it in the center of our chosen monitor
  402.     */
  403.     OffsetRect(
  404.         &tempRect,
  405.         params->qdGlobalsCopy->qdThePort->portRect.left + monitorRect.left,
  406.         params->qdGlobalsCopy->qdThePort->portRect.left + monitorRect.top);
  407.                         
  408.     /*
  409.     **    We align this on byte boundaries because CopyBits can blit it faster.
  410.     **    We do this so that if anything, it shrinks the rect a bit to
  411.     **    make sure it stays on the screen.
  412.     */
  413.     SetRect(
  414.         &alignedRect,
  415.         tempRect.left    - (tempRect.left    % kLongSize),
  416.         tempRect.top    + (kLongSize - (tempRect.top    % kLongSize)),
  417.         tempRect.right    + (kLongSize - (tempRect.right    % kLongSize)),
  418.         tempRect.bottom    - (tempRect.bottom    % kLongSize));
  419.                 
  420.     mBailIfNULL_((**outModule).view            = Q3View_New());
  421.  
  422.     mBailIfNULL_((**outModule).offscreen    = Offscreen_New(
  423.                                                 (CGrafPtr)params->qdGlobalsCopy->qdThePort,
  424.                                                 (const Rect *) &alignedRect,
  425.                                                 params->controlValues[kADParam_Dithered]));
  426.     /*
  427.     **    DRAW CONTEXT
  428.     */
  429.     mBailIfNULL_(theDrawContext        = Offscreen_NewPixmapDrawContext(
  430.                                         (**outModule).offscreen));
  431.     
  432.     mBailIfNot_(Q3View_SetDrawContext(
  433.                 (**outModule).view,
  434.                 theDrawContext));
  435.     
  436.     /*
  437.     **    RENDERER
  438.     */
  439.     mBailIfNULL_(theRenderer                = Q3ADUtility_NewRenderer());
  440.     
  441.     mBailIfNot_(Q3View_SetRenderer(
  442.                 (**outModule).view,
  443.                 theRenderer));
  444.     
  445.     /*
  446.     **    CAMERA
  447.     */
  448.     mBailIfNULL_(theCamera                    = iQ3ADModule_NewCamera((**outModule).numRows));
  449.     
  450.     mBailIfNot_(Q3View_SetCamera(
  451.                 (**outModule).view,
  452.                 theCamera));
  453.     
  454.     /*
  455.     **    LIGHT GROUP
  456.     */
  457.     mBailIfNULL_(theLightGroup                = iQ3ADModule_NewLightGroup((**outModule).numRows));
  458.     
  459.     mBailIfNot_(Q3View_SetLightGroup(
  460.                 (**outModule).view,
  461.                 theLightGroup));
  462.  
  463.     /*
  464.     **    SHADER
  465.     */
  466.     mBailIfNULL_((**outModule).shader        = Q3ADUtility_NewShader());
  467.     
  468. bail:
  469.     
  470.     if (theRenderer)
  471.         Q3Object_Dispose(theRenderer);
  472.         
  473.     if (theDrawContext)
  474.         Q3Object_Dispose(theDrawContext);
  475.         
  476.     if (theCamera)
  477.         Q3Object_Dispose(theCamera);
  478.         
  479.     if (theLightGroup)
  480.         Q3Object_Dispose(theLightGroup);
  481.         
  482.     if (status == kQ3Failure)
  483.         if(outModule) {
  484.             Q3ADModule_Dispose(outModule);
  485.             outModule    = NULL;
  486.         }
  487.     
  488.     return outModule;
  489. }
  490.  
  491.  
  492.  
  493. /*===========================================================================*\
  494.  *
  495.  *    Routine:    Q3ADModule_Dispose()
  496.  *
  497.  *    Comments:    
  498.  *
  499. \*===========================================================================*/
  500.  
  501. TQ3Status Q3ADModule_Dispose(TQ3ADModule **inModule)
  502. {
  503.     assert(inModule);    
  504.     if ((**inModule).view)
  505.         Q3Object_Dispose((**inModule).view);
  506.     if ((**inModule).shader)
  507.         Q3Object_Dispose((**inModule).shader);
  508.     if ((**inModule).offscreen)
  509.         Offscreen_Dispose((**inModule).offscreen);
  510.     DisposeHandle((Handle)inModule);
  511.     return kQ3Success;
  512. }
  513.  
  514.  
  515.  
  516. /*===========================================================================*\
  517.  *
  518.  *    Routine:    Q3ADModule_Draw()
  519.  *
  520.  *    Comments:    
  521.  *
  522. \*===========================================================================*/
  523.  
  524. TQ3Status Q3ADModule_Draw(
  525.             TQ3ADModule *inModule)
  526. {
  527.     TQ3Status        status        = kQ3Success;
  528.     TQ3ViewStatus    viewStatus    = kQ3ViewStatusRetraverse;
  529.     
  530.     mBailIfNot_(Q3View_StartRendering(inModule->view));
  531.     do {
  532.     
  533.         iQ3ADModule_Submit(inModule);
  534.         
  535.     } while ((viewStatus = Q3View_EndRendering(inModule->view)) == kQ3ViewStatusRetraverse);
  536.  
  537.     if (viewStatus == kQ3ViewStatusDone)
  538.         mBailIfNot_(Offscreen_Blit(inModule->offscreen));
  539.  
  540. bail:
  541.  
  542.     return status;
  543. }
  544.  
  545.  
  546.  
  547. #if 0
  548. #pragma mark -
  549. #endif
  550.  
  551. /******************************************************************************
  552.  **                                                                             **
  553.  **                        PUBLIC FUNCTION DEFINITIONS                             **
  554.  **                                                                             **
  555.  *****************************************************************************/
  556.  
  557. /*===========================================================================*\
  558.  *
  559.  *    Routine:    iQ3ADModule_ZeroOut()
  560.  *
  561.  *    Comments:    
  562.  *
  563. \*===========================================================================*/
  564.  
  565. TQ3Status iQ3ADModule_ZeroOut(TQ3ADModule *inModule)
  566. {
  567.     assert(inModule);
  568.         
  569.     inModule->view        = NULL;
  570.     inModule->shader    = NULL;
  571.     inModule->paneSize    = 1.0;
  572.     inModule->numRows    = 8;
  573.     inModule->offscreen    = NULL;
  574.     return kQ3Success;
  575. }
  576.  
  577.  
  578.  
  579. /*===========================================================================*\
  580.  *
  581.  *    Routine:    iQ3ADModule_NewCamera()
  582.  *
  583.  *    Comments:    
  584.  *
  585. \*===========================================================================*/
  586.  
  587. TQ3CameraObject iQ3ADModule_NewCamera(long numRows)
  588. {
  589.     TQ3ViewAngleAspectCameraData        perspectiveData;
  590.     
  591.     TQ3Point3D                     from     = { 11.5, 11.5, 15.0 };
  592.     TQ3Point3D                     to         = { 11.5, 11.5, 0.0 };
  593.     TQ3Vector3D                 up         = { 0.0, 1.0, 0.0 };
  594.     
  595.     float                         fieldOfView = 1.0;
  596.     float                         hither         = 0.001;
  597.     float                         yon         = 1000;
  598.     
  599.     up.x    = 0.0;
  600.     up.y    = 1.0;
  601.     up.z    = 0.0;
  602.  
  603.     
  604.     from.x = ((float) (kSize + kSpace) * numRows - kSpace) / 2.0;
  605.     from.y = from.x;
  606.     from.z = ((float) (kSize + kSpace) * numRows + (3 * kSpace));
  607.     
  608.     to.x = from.x;
  609.     to.y = to.x;
  610.  
  611.     #define    mCData    perspectiveData.cameraData
  612.  
  613.     mCData.placement.cameraLocation     = from;
  614.     mCData.placement.pointOfInterest     = to;
  615.     mCData.placement.upVector             = up;
  616.  
  617.     mCData.range.hither                    = hither;
  618.     mCData.range.yon                    = yon;
  619.  
  620.     mCData.viewPort.origin.x            = -1.0;
  621.     mCData.viewPort.origin.y            = 1.0;
  622.     mCData.viewPort.width                = 2.0;
  623.     mCData.viewPort.height                = 2.0;
  624.     
  625.     
  626.     perspectiveData.fov                    = fieldOfView;
  627.     perspectiveData.aspectRatioXToY        = 1.0;
  628.         
  629.     return Q3ViewAngleAspectCamera_New(&perspectiveData);
  630.     
  631.     #undef    mCData
  632. }
  633.  
  634.  
  635.  
  636. /*===========================================================================*\
  637.  *
  638.  *    Routine:    iQ3ADModule_NewLightGroup()
  639.  *
  640.  *    Comments:    
  641.  *
  642. \*===========================================================================*/
  643.  
  644. TQ3GroupObject    iQ3ADModule_NewLightGroup(long numRows)
  645. {
  646.     TQ3GroupObject            lightGroup = NULL;
  647.     TQ3LightData            lightData;
  648.     TQ3PointLightData        pointLightData;
  649.     TQ3DirectionalLightData    directionalLightData;
  650.     TQ3LightObject            ambientLight = NULL, pointLight = NULL, fillLight = NULL;
  651.     TQ3Point3D                pointLocation = { -10.0, 0.0, 0.0 };
  652.     TQ3Vector3D                fillDirection = { 10.0, 0.0, 10.0 };
  653.     TQ3ColorRGB                whiteLight = { 1.0, 1.0, 1.0 };
  654.     TQ3Status                status = kQ3Success;
  655.     
  656.     //    Set up light data for ambient light.  This light data will be used for point and fill
  657.     //    light also.
  658.  
  659.     lightData.isOn = kQ3True;
  660.     lightData.color = whiteLight;
  661.     
  662.     //    Create ambient light.
  663.     lightData.brightness = .5;
  664.     mBailIfNULL_(ambientLight = Q3AmbientLight_New(&lightData));
  665.  
  666.     //    Create point light.
  667.     lightData.brightness = 1.0;
  668.     pointLightData.lightData = lightData;
  669.     pointLightData.castsShadows = kQ3False;
  670.     pointLightData.attenuation = kQ3AttenuationTypeNone;
  671.     pointLocation.y = pointLocation.z = pointLocation.x = ((float) (kSize + kSpace) * numRows - kSpace) / 2.0;
  672.     pointLightData.location = pointLocation;
  673.     mBailIfNULL_(pointLight = Q3PointLight_New(&pointLightData));
  674.  
  675.     //    Create fill light.
  676.     lightData.brightness = .2;
  677.     directionalLightData.lightData = lightData;
  678.     directionalLightData.castsShadows = kQ3False;
  679.     directionalLightData.direction = fillDirection;
  680.     mBailIfNULL_(fillLight = Q3DirectionalLight_New(&directionalLightData));
  681.  
  682.     //    Create light group and add each of the lights into the group.
  683.     mBailIfNULL_(lightGroup = Q3LightGroup_New());
  684.  
  685.     mBailIfNot_(Q3Group_AddObject(lightGroup, ambientLight));
  686.  
  687.     mBailIfNot_(Q3Group_AddObject(lightGroup, pointLight));
  688.  
  689. //    mBailIfNot_(Q3Group_AddObject(lightGroup, fillLight));
  690.  
  691. bail:
  692.     if (ambientLight)
  693.         Q3Object_Dispose( ambientLight ) ;
  694.     
  695.     if (pointLight)
  696.         Q3Object_Dispose( pointLight ) ;
  697.     
  698.     if (fillLight)
  699.         Q3Object_Dispose( fillLight ) ;
  700.  
  701.     if (status == kQ3Failure)
  702.     {
  703.         if (lightGroup)
  704.             Q3Object_Dispose( lightGroup ) ;
  705.  
  706.         lightGroup =  NULL;
  707.     }
  708.     return lightGroup; 
  709. }
  710.  
  711.  
  712.  
  713. /*===========================================================================*\
  714.  *
  715.  *    Routine:    iQ3ADModule_Submit()
  716.  *
  717.  *    Comments:    
  718.  *
  719. \*===========================================================================*/
  720.  
  721. TQ3Status iQ3ADModule_Submit(
  722.             TQ3ADModule *inModule)
  723. {
  724.     TQ3BoxData                            myBoxData;
  725.     TQ3RotateAboutAxisTransformData        rotate;
  726.     
  727.     float                                pulse1,        pulse2,        pulse3,        pulse4,
  728.                                         sinpulse1,    sinpulse2,    sinpulse3,
  729.                                         randpulse1,    randpulse2,    randpulse3,
  730.                                         scaler;
  731.     
  732.     float                                rotationOrigin =
  733.                                             ((float)(kSize + kSpace) *
  734.                                             inModule->numRows - kSpace) / 2.0;
  735.                                             
  736.     TQ3ColorRGB                            diffuse;
  737.     int                                    idx, idy;
  738.     
  739.     TQ3Status                            status = kQ3Success;
  740.  
  741.     assert(inModule->view);
  742.     assert(inModule->shader);
  743.  
  744.     
  745.     /*
  746.     **    Initialize our utilities (this just gets a current tick count)
  747.     **    to base it's further calculations on
  748.     */
  749.     mQ3ADUtility_Begin();
  750.     
  751.     /*
  752.     **    Grab off some pulses from the utilities (the parameters are in ticks)
  753.     **    If you pass in prime numbers, the pulses will never sync up
  754.     **    so you get this great organic kind of thing
  755.     **
  756.     **    Did you ever read "A Wrinkle In Time?" by Madeline L'Engle?
  757.     **    There's this great scene with this huge pulsating brain
  758.     **    which gets everyone in the whole city to sync up with it.
  759.     **    After a while, the whole town is sucked in to the rhythm and it
  760.     **    takes over their minds.
  761.     */
  762.     pulse1        = mQ3ADUtility_GetPulse(600);
  763.     pulse2        = mQ3ADUtility_GetPulse(407);
  764.     pulse3        = mQ3ADUtility_GetPulse(1423);
  765.     pulse4        = mQ3ADUtility_GetPulse(750);
  766.     
  767.     /*
  768.     **    Run 'em through a sin wave
  769.     */
  770.     sinpulse1    = sin(pulse1);
  771.     sinpulse2    = sin(pulse2);
  772.     sinpulse3    = sin(pulse3);
  773.                                         
  774.     randpulse1    = sinpulse2 * sinpulse3;
  775.     randpulse2    = sinpulse1 * sinpulse2;    
  776.     randpulse3    = sinpulse1 * sinpulse3;    
  777.                                                                     
  778.     scaler        = fabs(sinpulse1) * (kSpace + kSize);
  779.  
  780.     diffuse.r = Q3ADUtility_GetNumInRange(sinpulse1, 1.0, 0.5);
  781.     diffuse.g = Q3ADUtility_GetNumInRange(sinpulse2, 1.0, 0.5);
  782.     diffuse.b = Q3ADUtility_GetNumInRange(sinpulse3, 1.0, 0.5);
  783.     
  784.  
  785.     myBoxData.faceAttributeSet = NULL;
  786.     myBoxData.boxAttributeSet = NULL;
  787.         
  788.     Q3Point3D_Set(
  789.         &rotate.origin,
  790.         rotationOrigin,
  791.         rotationOrigin,
  792.         0);
  793.                 
  794.     Q3Vector3D_Set(
  795.         &rotate.orientation,
  796.         sinpulse3,
  797.         randpulse1,
  798.         randpulse2);
  799.         
  800.     rotate.radians = pulse1;
  801.     
  802.     Q3Vector3D_Set(
  803.         &myBoxData.orientation,
  804.         Q3ADUtility_GetNumInRange(sinpulse2, 0.0, 0.25) * 2,
  805.         Q3ADUtility_GetNumInRange(sinpulse2, 1.0, 0.50) * 2,
  806.         0);
  807.         
  808.     Q3Vector3D_Set(
  809.         &myBoxData.majorAxis,
  810.         0,
  811.         Q3ADUtility_GetNumInRange(randpulse3, 0.0, 0.25) * 2,
  812.         Q3ADUtility_GetNumInRange(scaler,     1.0, 0.50) * 2);
  813.         
  814.     Q3Vector3D_Set(
  815.         &myBoxData.minorAxis,
  816.         Q3ADUtility_GetNumInRange(randpulse1, 1.0, 0.50) * 2,
  817.         0,
  818.         Q3ADUtility_GetNumInRange(randpulse2, 0.0, 0.25) * 2);
  819.  
  820.  
  821.     Q3BackfacingStyle_Submit(
  822.         kQ3BackfacingStyleRemove,
  823.         inModule->view);
  824.         
  825.     Q3Object_Submit(
  826.         inModule->shader,
  827.         inModule->view);
  828.         
  829.     Q3RotateAboutAxisTransform_Submit(
  830.         &rotate,
  831.         inModule->view);
  832.         
  833.     Q3Attribute_Submit(
  834.         kQ3AttributeTypeDiffuseColor,
  835.         &diffuse,
  836.         inModule->view);
  837.     
  838.     for (idx = 0; idx < inModule->numRows; idx++) {
  839.     
  840.         for (idy = 0; idy < inModule->numRows; idy++) {
  841.         
  842.             Q3Point3D_Set(&myBoxData.origin, idx * (kSize + kSpace),
  843.                 idy * (kSize + kSpace), 0);
  844.                 
  845.             Q3Box_Submit(&myBoxData, inModule->view);
  846.         }
  847.     }
  848.  
  849. bail:
  850.  
  851.     mQ3ADUtility_End();
  852.  
  853.     return status;
  854. }
  855.  
  856.  
  857.